package com.ms.game.sendgift;

import java.math.BigDecimal;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map.Entry;

import com.ms.game.common.container.GameLimitInfo;
import com.ms.game.itembox.ChangeItemLister;
import com.ms.game.itembox.Item;
import com.ms.game.itembox.ItemChangeWay;
import com.ms.game.itembox.container.ItemBasic;
import com.ms.game.itembox.db.PlayerItemModel;
import com.ms.game.itembox.message.SSimpleItem;
import com.ms.game.lobby.GameLobbyModule;
import com.ms.game.password.db.PasswordErrorWay;
import com.ms.game.sendgift.db.LoadAllNotifyDCLAsync;
import com.ms.game.sendgift.db.LoadAllNotifyDataAsync;
import com.ms.game.sendgift.db.LoadGiftRecordDataAsync;
import com.ms.game.sendgift.db.LoadRecordDetailDataAsync;
import com.ms.game.sendgift.db.LoadSendGiftOrderDCLAsync;
import com.ms.game.sendgift.db.SaveGiftNotifyAnswerAsync;
import com.ms.game.sendgift.db.SaveGiftNotifyTakenStageAsync;
import com.ms.game.sendgift.db.SaveGiftRecordLogAsync;
import com.ms.game.sendgift.db.SaveSendGiftNotifyDataAsync;
import com.ms.game.sendgift.db.SendGiftNotifyModel;
import com.ms.game.sendgift.db.SendGiftRecordLog;
import com.ms.game.sendgift.db.checkPasswordForGiftDCLAsync;
import com.ms.game.sendgift.message.SendGiftAllNotifyResponse;
import com.ms.game.sendgift.message.SendGiftNotifyMessage;
import com.ms.game.sendgift.message.SendGiftRequest;
import com.ms.game.sendgift.message.SendGiftResponse;
import com.ms.player.Player;
import com.ms.service.error.ErrorCode;
import com.ms.service.module.analysisgroup.AnalysisGroupProcessor;
import com.ms.service.module.analysisgroup.CoinExpenditureWay;
import com.ms.service.module.commonsettings.CommonSendGiftSetting;
import com.xpec.c4.game.common.Helper;
import com.xpec.c4.game.datamanager.BaseDataInfo;
import com.xpec.c4.game.datamanager.ResultNo;
import com.xpec.c4.game.datamanager.agent.money.ChangeCoin;
import com.xpec.c4.game.datamanager.agent.money.ChangeCoinLister;
import com.xpec.c4.game.datamanager.agent.money.CoinType;
import com.xpec.c4.game.datamanager.agent.money.MoneyChangeWay;
import com.xpec.c4.game.datamanager.agent.moneyItem.MoneyItemChangeParam;
import com.xpec.c4.game.system.InitData;
import com.xpec.c4.game.time.TimeConstants;
import com.xpec.c4.game.time.TimeSys;
import com.xpec.c4.game.utility.GUID;
import com.xpec.c4.game.utility.GUIDFactory;
import com.xpec.c4.game.utility.GameUtility;
import com.xpec.c4.message.MessageTypes;
import com.xpec.c4.service.message.MessageAction;
import com.xpec.c4.service.module.BasicServiceModule;
import com.xpec.c4.service.module.common.ItemInfoManager;
import com.xpec.c4.service.module.common.PlayerCommonInfoManager;

public class SendGiftProcessor {
	/** 發送禮物最低等級*/
//	public static final int SEND_GIFT_MIN_LEVEL = 50;	2017/06/07 轉由commonSettings判斷
	
	/** 接收禮物最低等級*/
	public static final int RECEIVE_GIFT_MIN_LEVEL = 1;
	
	/** 發送禮物最低持有金額*/
//	public static final int SEND_GIFT_MIN_MONEY = 30000;	2017/06/07 轉由commonSettings判斷
	
	/**
	 * 送禮手續費
	 */
//	public static final float SERVICE_CHARGE = 0.0f;	2017/06/07 轉由commonSettings判斷
	
	/**
	 * 送道具最多種類
	 */
	public static final int SEND_ITEM_MAX_KIND = 5;
	
	/**
	 * 送道具最多數量
	 */
	public static final int SEND_ITEM_MAX_NUMBER = 99;
	
	/**
	 * 保留時間(2天)
	 */
	public static final long SEND_GIFT_KEEP_TIME = 3 * TimeConstants.MILLI_SECOND_PRE_DAY; 

	
	public static final int WEB_TRANSACTION_RECORD_MAX_PRE_PAGE = 5;
	

	/**
	 * @param sessionID
	 * 發送禮物第一步驟，寄送通知
	 */
	public static void OnSendGiftFirstStep(GUID sessionID , SendGiftRequest request, GameLobbyModule module){
		
		SendGiftResponse response = new SendGiftResponse();
		
		int messageType = MessageTypes.S_GIFT_FIRST_SEND_RESPONSE;
		
		if (module.isStopTransaction()) {
			response.errorCode = ErrorCode.GAME_SERVER_WAIT_TO_CLOSE;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		Player playerData = null;
		GUID playerID = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		if (playerID != null) {
			playerData = module.getZone().getPlayer(playerID);
		}
		
		if (playerData == null) {
			// 是否有玩家資料
			response.errorCode = ErrorCode.NO_PLAYER_DATA;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		GUID accountID = PlayerCommonInfoManager.getInstance().getAccountIdByPlayerGuid(playerID);
		if (accountID == null) {
			// 是否有帳號資料
			response.errorCode = ErrorCode.NO_ACCOUNT_DATA;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		//確認會員限制
		int limitCode = GameLimitInfo.checkLimitByClassify(GameLimitInfo.TRANS_SEND_GIFT, playerData.getVip(), playerData.getLevel(), playerData.isVerifiedMember(), playerData.isTrialAccount(), playerData.getUplineCode());
		if (limitCode != GameLimitInfo.TRUE) {
			response.errorCode = GameLimitInfo.limitToErrorCode(limitCode);
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		CommonSendGiftSetting sendGiftSetting = module.getCommonSettings().getSendGiftSetting();
		if(sendGiftSetting == null){
			response.errorCode = ErrorCode.DATA_NOT_FOUND;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		//等級限制(從GameLimitInfo移出來判斷)
		int limitSendLevel = sendGiftSetting.getLimitMinLevel();
		if(playerData.getLevel() < limitSendLevel){
			response.errorCode = ErrorCode.PLAYER_LEVEL_NOT_ENOUGH;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		if (playerData.getDisableSendGiftTime() > TimeSys.currentTimeMills() || playerData.getDisableSendGiftTime() == -1) {
			// 玩家被GMTOOL禁止送禮 -1是永久禁止
			response.errorCode = ErrorCode.SEND_GIFT_DISABLE;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		if (request == null) {
			// 參數不正確
			response.errorCode = ErrorCode.INVALID_PARAM;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}

		//是否在線上
		if (request.targetName == null || request.targetName.equals("")) {
			// 沒有對象資料
			response.errorCode = ErrorCode.NO_TARGET_DATA;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		GUID targetID = PlayerCommonInfoManager.getInstance().getGuidByPlayerName(request.targetName);
		
		//手續費
		float fee = sendGiftSetting.getPercentageOfFee();
		long charge = (long) (Math.ceil(request.sendMoney * fee));
		
		int limitMinMoney = sendGiftSetting.getLimitMinMoney();
		BigDecimal restMoney = Helper.add(playerData.getGoldCoin(), new BigDecimal(-request.sendMoney), new BigDecimal(-charge));
		boolean moneyEnough = Helper.isGreaterEqual(restMoney, new BigDecimal(limitMinMoney));
		//送出錢後自身金錢不得小於SEND_GIFT_MIN_MONEY
		if (request.sendMoney < 0 || !moneyEnough) {
			// 送禮物金錢不夠
			response.errorCode = ErrorCode.SEND_GIFT_MONEY_NOT_ENOUGH;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		if (request.items.size() > SEND_ITEM_MAX_KIND) {
			// 道具種類超過
			response.errorCode = ErrorCode.SEND_GIFT_ITEM_OVERFLOW;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		int count = 0;
		//判斷是否有道具
		for (Entry<String, Integer> item : request.items.entrySet()) {
			String reqItemSn = item.getKey();
			int reqItemCount = item.getValue();

			//取出道具
			Item sendItem = playerData.getItemBox().getItem(reqItemSn);
			if (sendItem == null){
				response.errorCode = ErrorCode.ITEM_NOT_FOUND_FROM_PLAYER;
				MessageAction.sendMessage(sessionID, messageType, response);
				return;
			}
			
			ItemBasic itemBasic = ItemInfoManager.getInstance().getItem(sendItem.getItemId());
			if(itemBasic == null){
				response.errorCode = ErrorCode.ITEM_NOT_FOUND_FROM_BIN;
				MessageAction.sendMessage(sessionID, messageType, response);
				return;
			}
			
			if(!itemBasic.isCanTrade()){
				// 不能交易的
				response.errorCode = ErrorCode.ITEM_CAN_NOT_TRADE;
				MessageAction.sendMessage(sessionID, messageType, response);
				return;
			}
			
		
			if(itemBasic.isCanRefine() &&  sendItem.getRefineLevel() == 0){
				//可以精煉但是精煉等級是0的(沒有精煉過)
				response.errorCode = ErrorCode.SEND_GIFT_ITEM_NOT_REFINE;
				MessageAction.sendMessage(sessionID, messageType, response);
				return;
			}
			
			count = sendItem.getCount();
			if (count == 0 || count < reqItemCount) {
				response.errorCode = ErrorCode.SEND_GIFT_ITEM_NOT_ENOUGH;
				MessageAction.sendMessage(sessionID, messageType, response);
				return;
			}
			if (reqItemCount > SEND_ITEM_MAX_NUMBER) {
				response.errorCode = ErrorCode.SEND_GIFT_ITEM_OVERFLOW;
				MessageAction.sendMessage(sessionID, messageType, response);
				return;
			}
		}
		
		SendGiftNotifyModel sendGiftNotifyModel = new SendGiftNotifyModel();
		
	}
	
	
	/**
	 * from
	 * @see GameLobbyModule#sendGiftFirstCallBack
	 *
	 * @param messageType MessageTypes.S_GIFT_FIRST_SEND_RESPONSE
	 * @param sessionID
	 * @param playerData 送方 player
	 * @param targetData 收方 player
	 * @param charge
	 * @param items
	 * @param module
	 * @param param 
	 * @param isFromWeb 是否是Web虛寶交易
	 * @return
	 */
	public static int OnSendGiftFirstStepCallBack(int messageType, GUID sessionID, Player playerData, Player targetData, long charge,
			HashMap<String, Integer> items, BasicServiceModule module, MoneyItemChangeParam param, 
			long sendOrderId, String orderNum ,boolean isFromWeb) {
		
		SendGiftResponse response = new SendGiftResponse();

		if (param.getResult() != ResultNo.OK) {
			// DC金錢失敗
			if (!isFromWeb) {
				response.errorCode = param.getResult();
				MessageAction.sendMessage(sessionID, messageType, response);
			}
			return param.getResult();
		}

		ChangeCoin coin = null;
		ChangeCoinLister CoinLister = param.getMoneyParam().getChangeCoinLister();
		if (CoinLister != null) {
			coin = CoinLister.getCoinMap().get(CoinType.GOLD);
		}

		// 寄送道具資料清單
		HashMap<String, Integer> itemMap = new HashMap<String, Integer>();	
		ArrayList<Item> sendGiftItemList = param.getItemParam().getSendGiftItemList();
		for (Item senditem : sendGiftItemList) {
			itemMap.put(senditem.getSn(), senditem.getCount());
		}

		// 建立交易訂單
		SendGiftNotifyModel notiftModel = new SendGiftNotifyModel();
		notiftModel.setOrderID(param.getOrderId().toString());
		notiftModel.setSendOrderID(sendOrderId);
		notiftModel.setOrderNumber(orderNum);
		notiftModel.setPlayerGUID(playerData.getGuid().toString());
		notiftModel.setPlayerName(param.getPlayerName());
		notiftModel.setSenderFacePhoto(playerData.getFacephoto());
		notiftModel.setTargetGUID(targetData.getGuid().toString());
		notiftModel.setTargetName(targetData.getNameWithNumber());
		notiftModel.setTargetFacePhoto(targetData.getFacephoto());
		if (coin != null) {
			notiftModel.setGoldCoin(coin.getChangeValue().longValue() - charge);
			notiftModel.setServiceCharge(charge);
		}
		notiftModel.setStage(SendGiftStage.FIRST_CREATE);
		notiftModel.setItems(itemMap);
		long createTime = TimeSys.currentTimeMills();
		notiftModel.setCreateTime(GameUtility.longToDate(createTime));
		long timeOut = createTime + SEND_GIFT_KEEP_TIME;
		notiftModel.setOverTime(GameUtility.longToDate(timeOut));
		notiftModel.setFinish(false);
		notiftModel.setTaken(false);

		// 記錄下log
		SaveSendGiftNotifyDataAsync saveData = new SaveSendGiftNotifyDataAsync();
		saveData.messageType = messageType;
		saveData.model = notiftModel;
		saveData.sendGiftItemList = sendGiftItemList;
		if (coin != null) {
			saveData.newValue = coin.getNewValue();
		}
		else{
			saveData.newValue = BigDecimal.ZERO;
		}
		saveData.sessionID = sessionID;
		saveData.playerIP = playerData.getLastloginIP();
		saveData.key = transformOrderIdToGuid(notiftModel.getSendOrderID());
		module.addAsyncCommand(saveData);
		
		//送給C幣統計
		AnalysisGroupProcessor.sendCoinExpenditureToAnalysis(CoinExpenditureWay.SEND_GIFT_CHARGE, new BigDecimal(charge));
		
		return ErrorCode.SUCCESS;
	}
	
	
	/**
	 * @param sessionID
	 * 發送禮物第一步驟，取消請求
	 */
	public static void OnSendGiftCancelFirstStep(GUID sessionID , SendGiftRequest request, GameLobbyModule module){
		SendGiftResponse response = new SendGiftResponse();
		
		int messageType = MessageTypes.S_GIFT_FIRST_CANCEL_RESPONSE;
		
		if(module.isStopTransaction()){
			response.errorCode = ErrorCode.GAME_SERVER_WAIT_TO_CLOSE;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		if(request == null){
			//參數不正確
			response.errorCode = ErrorCode.INVALID_PARAM;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		Player playerData =null;
		GUID playerID = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		if(playerID != null){
			playerData = module.getZone().getPlayer(playerID);
		}
		if(playerData == null){
			//是否有玩家資料
			response.errorCode = ErrorCode.NO_PLAYER_DATA;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		if(playerData.getLevel() < RECEIVE_GIFT_MIN_LEVEL){
			//玩家等級不足
			response.errorCode = ErrorCode.PLAYER_LEVEL_NOT_ENOUGH;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		if(request.orderID == 0L){
			//沒有訂單資料
			response.errorCode = ErrorCode.SEND_GIFT_ORDER_NULL;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		GiftPlayerData giftData = new GiftPlayerData();
		giftData.module = module;
		giftData.sessionID = sessionID;
		giftData.response = response;
		giftData.playerData = playerData;
		
		LoadSendGiftOrderDCLAsync loadData = new LoadSendGiftOrderDCLAsync();
		loadData.setQueueID(request.orderID.hashCode()); //分配道相同執行緒用
		loadData.orderID = request.orderID;
		loadData.playerID = playerID;
		loadData.messageType = messageType;
		loadData.nextStage = SendGiftStage.FIRST_CANCEL;
		module.addCentralAsyncCommand(loadData,giftData);
	}
	
	
	/**
	 * @param sessionID
	 * @param model
	 * @param response
	 * 獲得訂單資料後做判斷
	 * DC callback
	 * {@link GameLobbyModule#sendGiftCallBackCancel(BaseDataInfo, Object...)}
	 */
	public static void OnSendGiftCancelFirstStepCallBack(int messageType, GiftPlayerData giftData, SendGiftNotifyModel model, GameLobbyModule module) {
		//log 記錄
		SendGiftRecordLog logModel = new SendGiftRecordLog();
		logModel.setOrderID(model.getOrderID());
		logModel.setSendOrderID(model.getSendOrderID());
		logModel.setOrderNumber(model.getOrderNumber());
		logModel.setPlayerGUID(model.getPlayerGUID());
		logModel.setPlayerName(model.getPlayerName());
		logModel.setPlayerIP(giftData.playerData.getLastloginIP());
		logModel.setTargetGUID(model.getTargetGUID());
		logModel.setTargetName(model.getTargetName());
		logModel.setGoldCoin(model.getGoldCoin());
		logModel.setServiceCharge(model.getServiceCharge());
		logModel.setItems(model.getItems());
		logModel.setStage(model.getStage());
		logModel.setCreateTime(model.getCreateTime());
		logModel.setAnswerTime(model.getAnswerTime());
		logModel.setOrderFinishTime(model.getOrderFinishTime());
		logModel.setFinalTakenTime(model.getFinalTakenTime());
		logModel.setOverTime(model.getOverTime());
		logModel.setSuccess(false);
		logModel.setFinish(model.isFinish());
		logModel.setTaken(model.isTaken());
		
		SaveGiftRecordLogAsync saveLog = new SaveGiftRecordLogAsync();
		saveLog.logModel = logModel;
		saveLog.key = transformOrderIdToGuid(logModel.getSendOrderID());
		module.addAsyncCommand(saveLog);
		
		LoadSendGiftOrderDCLAsync loadData = new LoadSendGiftOrderDCLAsync();
		loadData.setQueueID(String.valueOf(model.getSendOrderID()).hashCode()); //分配道相同執行緒用
		loadData.orderID = model.getSendOrderID();
		loadData.playerID = giftData.playerData.getGuid();
		loadData.messageType = messageType;
		loadData.nextStage = SendGiftStage.FIRST_CANCEL;
		module.addCentralAsyncCommand(loadData,giftData);
	}
	
	public static void OnSendGiftCancelFirstStepCallBack2(int messageType, GiftPlayerData giftData, SendGiftNotifyModel model, ArrayList<PlayerItemModel> sendGiftItems){
		
		Player player = giftData.playerData;
		GameLobbyModule module = giftData.module;
		
		//log 記錄
		SendGiftRecordLog logModel = new SendGiftRecordLog();
		logModel.setOrderID(model.getOrderID());
		logModel.setSendOrderID(model.getSendOrderID());
		logModel.setOrderNumber(model.getOrderNumber());
		logModel.setPlayerGUID(model.getPlayerGUID());
		logModel.setPlayerName(model.getPlayerName());
		logModel.setPlayerIP(giftData.playerData.getLastloginIP());
		logModel.setTargetGUID(model.getTargetGUID());
		logModel.setTargetName(model.getTargetName());
		logModel.setGoldCoin(model.getGoldCoin());
		logModel.setServiceCharge(model.getServiceCharge());
		logModel.setItems(model.getItems());
		logModel.setStage(model.getStage());
		logModel.setCreateTime(model.getCreateTime());
		logModel.setAnswerTime(model.getAnswerTime());
		logModel.setOrderFinishTime(model.getOrderFinishTime());
		logModel.setFinalTakenTime(model.getFinalTakenTime());
		logModel.setOverTime(model.getOverTime());
		logModel.setSuccess(false);
		logModel.setFinish(model.isFinish());
		logModel.setTaken(model.isTaken());
		
		SaveGiftRecordLogAsync saveLog = new SaveGiftRecordLogAsync();
		saveLog.logModel = logModel;
		saveLog.key = transformOrderIdToGuid(logModel.getSendOrderID());
		module.addAsyncCommand(saveLog);
		
		HashMap<String, SSimpleItem> itemsMap = new HashMap<String, SSimpleItem>();
		for (PlayerItemModel itemModel : sendGiftItems) {
			Item item = new Item(itemModel);
			itemsMap.put(item.getSn(), item.toClientFormat());
		}
		
		//記錄下要傳送給自己的資訊
		SendGiftResponse response = new SendGiftResponse();
		response.orderID = model.getSendOrderID();
		response.returnGoldCoin = model.getGoldCoin();
		response.charge = model.getServiceCharge();
		response.items = itemsMap;
		
		//記錄下要傳送給對方的資訊
		SendGiftNotifyMessage notify = new SendGiftNotifyMessage();
		notify.answer = false;
		notify.fromName = player.getNameWithNumber();
		notify.orderID = model.getSendOrderID();
		
		ChangeCoinLister coinLister = new ChangeCoinLister();
		ChangeItemLister itemLister = new ChangeItemLister();
		if (sendGiftItems != null) {
			itemLister.addSendGiftOrderId(model.getOrderID());
			for (PlayerItemModel itemModel : sendGiftItems) {
				itemLister.addItem(itemModel.getSn(), itemModel.getItemId(), itemModel.getCount(), itemModel.getRefineLevel());
			}
		}
		
		//有加手續費
		BigDecimal goldCoin = Helper.add(new BigDecimal(response.returnGoldCoin), new BigDecimal(response.charge));
		coinLister.addCoin(CoinType.GOLD, goldCoin);
		//金錢寫回DC，給自己
		
		module.getPlayerDataAgent().updatePlayerMoneyAndItemToDC(GUID.parseUUID(model.getOrderID()), player, 
				coinLister, MoneyChangeWay.ADD_GIFT_RETURN,
				itemLister, ItemChangeWay.ADD_GIFT_RETURN,
				null, null, null, module, "sendGiftCallBackCancel", 
				GUID.parseUUID(model.getPlayerGUID()),  GUID.parseUUID(model.getTargetGUID()), 
				response, notify);
	}
	
	
	/**
	 * @param sessionID
	 * @param request
	 * @param module
	 * 收方，是否接受禮物
	 */
	public static void OnSendGiftSecondAccept(GUID sessionID , SendGiftRequest request, GameLobbyModule module){
		
		SendGiftResponse response = new SendGiftResponse();
		
		int messageType = MessageTypes.S_GIFT_SECOND_ACCEPT_RESPONSE ;
		
		if(request == null){
			//參數不正確
			response.errorCode = ErrorCode.INVALID_PARAM;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		if(module.isStopTransaction()){
			response.errorCode = ErrorCode.GAME_SERVER_WAIT_TO_CLOSE;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		Player playerData =null;
		GUID playerID = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		if(playerID != null){
			playerData = module.getZone().getPlayer(playerID);
		}
		if(playerData == null){
			//是否有玩家資料
			response.errorCode = ErrorCode.NO_PLAYER_DATA;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		//確認會員限制
		int limitCode = GameLimitInfo.checkLimitByClassify(GameLimitInfo.TRANS_REV_GIFT, playerData.getVip(),playerData.getLevel(), playerData.isVerifiedMember(), playerData.isTrialAccount(), playerData.getUplineCode());
		if(limitCode != GameLimitInfo.TRUE){
			response.errorCode = GameLimitInfo.limitToErrorCode(limitCode);
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}	
		
		if(playerData.getLevel() < RECEIVE_GIFT_MIN_LEVEL){
			//玩家等級不足
			response.errorCode = ErrorCode.PLAYER_LEVEL_NOT_ENOUGH;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
	
		if(request.orderID == 0L){
			//沒有訂單資料
			response.errorCode = ErrorCode.SEND_GIFT_ORDER_NULL;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		
		boolean answer = request.answer; 
		//回覆是或否
		response.answer = answer;
		
		GiftPlayerData giftData = new GiftPlayerData();
		giftData.module = module;
		giftData.sessionID = sessionID;
		giftData.response = response;
		giftData.playerData = playerData;
		
		LoadSendGiftOrderDCLAsync loadData = new LoadSendGiftOrderDCLAsync();
		loadData.messageType = messageType;
		loadData.setQueueID(request.orderID.hashCode()); //分配道相同執行緒用
		loadData.orderID = request.orderID;
		loadData.playerID = playerID;
		loadData.nextStage = answer ? SendGiftStage.SECOND_ACCEPT : SendGiftStage.SECOND_REJECT;
		module.addCentralAsyncCommand(loadData, giftData);
		
		
	}
	
	/**
	 * @param sessionID
	 * @param model
	 * @param response
	 * 獲得訂單資料後做判斷
	 */
	public static void OnSendGiftSecondAcceptCallBack(int messageType, GUID sessionID, Player playerData, SendGiftNotifyModel model, 
		 SendGiftResponse response, GameLobbyModule module) {
		
		SaveGiftNotifyAnswerAsync saveData = new SaveGiftNotifyAnswerAsync();
		saveData.key = transformOrderIdToGuid(model.getSendOrderID());
		saveData.messageType = messageType;
		saveData.model = model;
		saveData.playerName = playerData.getNameWithNumber();
		saveData.orderID = model.getSendOrderID();
		saveData.sessionID = sessionID;
		saveData.targetIP = playerData.getLastloginIP();
		saveData.response = response;
		saveData.targetGUID = GUID.parseUUID(model.getPlayerGUID());
		module.addAsyncCommand(saveData);
		
	}
	
	/**
	 * @param sessionID
	 * @param request
	 * @param module
	 * 送方做最後確認，確認就發送
	 */
	public static void OnSendGiftFinialAccept(GUID sessionID , SendGiftRequest request, GameLobbyModule module){
		
		int messageType = MessageTypes.S_GIFT_FINIAL_GIVE_RESPONSE;
		
		SendGiftResponse response = new SendGiftResponse();
		
		if(request == null){
			//參數不正確
			response.errorCode = ErrorCode.INVALID_PARAM;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		if(module.isStopTransaction()){
			response.errorCode = ErrorCode.GAME_SERVER_WAIT_TO_CLOSE;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		if(request.answer == false){
			//20160717 : 第三步 不提供取消的功能 所以如果是false 就return
			return;
		}
		
		Player playerData =null;
		GUID playerID = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		if(playerID != null){
			playerData = module.getZone().getPlayer(playerID);
		}
		if(playerData == null){
			//是否有玩家資料
			response.errorCode = ErrorCode.NO_PLAYER_DATA;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		GUID accountID = PlayerCommonInfoManager.getInstance().getAccountIdByPlayerGuid(playerID);
		if(accountID == null){
			//是否有帳號資料
			response.errorCode = ErrorCode.NO_ACCOUNT_DATA;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		//確認會員限制
		int limitCode = GameLimitInfo.checkLimitByClassify(GameLimitInfo.TRANS_SEND_GIFT, playerData.getVip(),playerData.getLevel(), playerData.isVerifiedMember(), playerData.isTrialAccount(), playerData.getUplineCode());
		if(limitCode != GameLimitInfo.TRUE){
			response.errorCode = GameLimitInfo.limitToErrorCode(limitCode);
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}	
		
		CommonSendGiftSetting sendGiftSetting = module.getCommonSettings().getSendGiftSetting();
		if(sendGiftSetting == null){
			response.errorCode = ErrorCode.DATA_NOT_FOUND;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		int limitSendLevel = sendGiftSetting.getLimitMinLevel();
		if(playerData.getLevel() < limitSendLevel){
			//玩家等級不足
			response.errorCode = ErrorCode.PLAYER_LEVEL_NOT_ENOUGH;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		//密碼全轉大寫
		request.password = request.password.toUpperCase();
		
		if(request.orderID == 0L){
			//沒有訂單資料
			response.errorCode = ErrorCode.SEND_GIFT_ORDER_NULL;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		if(playerData.getDisableTimeGift() > TimeSys.currentTimeMills()){
			//密碼錯誤太多次 被禁止送禮
			response.errorCode = ErrorCode.PASSWORD_ERROR_DISABLE_TIME;
			response.disableTime = playerData.getDisableTimeGift();
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		//回覆是或否
		response.answer = request.answer; 
		
		GiftPlayerData giftData = new GiftPlayerData();
		giftData.module = module;
		giftData.sessionID = sessionID;
		giftData.response = response;
		giftData.playerData = playerData;
		
		LoadSendGiftOrderDCLAsync loadData = new LoadSendGiftOrderDCLAsync();
		loadData.messageType = messageType;
		loadData.setQueueID(request.orderID.hashCode()); //分配道相同執行緒用
		loadData.orderID = request.orderID;
		loadData.playerID = playerID;
		loadData.nextStage = SendGiftStage.FINIAL_SEND;
		
		checkPasswordForGiftDCLAsync checkData = new checkPasswordForGiftDCLAsync();
		loadData.setQueueID(request.orderID.hashCode());
		checkData.accountID = accountID;
		checkData.playerID = playerID;
		checkData.playName = playerData.getNameWithNumber();
		checkData.stage = SendGiftStage.FINIAL_SEND;
		checkData.password = request.password;
		checkData.errorWay = PasswordErrorWay.ERROR_SENDGIFT;
		checkData.orderID = request.orderID;
		module.addCentralAsyncCommand(checkData, module, response, loadData,
				messageType, sessionID,giftData);
	}
	
	
	/**
	 * @param sessionID
	 * @param model
	 * @param response
	 * 最後送方確認送出
	 */
	public static void OnSendGiftFinalAcceptCallBack(int messageType, GUID sessionID, Player playerData, SendGiftNotifyModel model, 
			 SendGiftResponse response, GameLobbyModule module) {
		
		SaveGiftNotifyAnswerAsync saveData = new SaveGiftNotifyAnswerAsync();
		saveData.messageType = messageType;
		saveData.model = model;
		saveData.playerName = playerData.getName();
		saveData.orderID = model.getSendOrderID();
		saveData.sessionID = sessionID;
		saveData.playerIP = playerData.getLastloginIP();
		saveData.response = response;
		saveData.targetGUID = GUID.parseUUID(model.getTargetGUID());
		saveData.success = true;
		saveData.key = transformOrderIdToGuid(model.getSendOrderID());
		module.addAsyncCommand(saveData);
	}
	
	public static void OnSendGiftGetRejectedOrder(GUID sessionID ,SendGiftRequest request, GameLobbyModule module){
		SendGiftResponse response = new SendGiftResponse();
		
		int messageType = MessageTypes.S_GIFT_GET_REJECTED_ORDER_RESPONSE;


		if(request == null){
			//參數不正確
			response.errorCode = ErrorCode.INVALID_PARAM;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		if(module.isStopTransaction()){
			response.errorCode = ErrorCode.GAME_SERVER_WAIT_TO_CLOSE;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		Player playerData =null;
		GUID playerID = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		if(playerID != null){
			playerData = module.getZone().getPlayer(playerID);
		}
		if(playerData == null){
			//是否有玩家資料
			response.errorCode = ErrorCode.NO_PLAYER_DATA;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		GUID accountID = PlayerCommonInfoManager.getInstance().getAccountIdByPlayerGuid(playerID);
		if(accountID == null){
			//是否有帳號資料
			response.errorCode = ErrorCode.NO_ACCOUNT_DATA;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		//確認會員限制
		int limitCode = GameLimitInfo.checkLimitByClassify(GameLimitInfo.TRANS_SEND_GIFT, playerData.getVip(),playerData.getLevel(), playerData.isVerifiedMember(), playerData.isTrialAccount(), playerData.getUplineCode());
		if(limitCode != GameLimitInfo.TRUE){
			response.errorCode = GameLimitInfo.limitToErrorCode(limitCode);
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}	
		
		CommonSendGiftSetting sendGiftSetting = module.getCommonSettings().getSendGiftSetting();
		if(sendGiftSetting == null){
			response.errorCode = ErrorCode.DATA_NOT_FOUND;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		int limitSendLevel = sendGiftSetting.getLimitMinLevel();
		if(playerData.getLevel() < limitSendLevel){
			//玩家等級不足
			response.errorCode = ErrorCode.PLAYER_LEVEL_NOT_ENOUGH;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		GiftPlayerData giftData = new GiftPlayerData();
		giftData.module = module;
		giftData.sessionID = sessionID;
		giftData.response = response;
		giftData.playerData = playerData;

		LoadSendGiftOrderDCLAsync loadData = new LoadSendGiftOrderDCLAsync();
		loadData.messageType = messageType;
		loadData.setQueueID(request.orderID.hashCode()); //分配道相同執行緒用
		loadData.orderID = request.orderID;
		loadData.playerID = playerID;
		loadData.nextStage = SendGiftStage.SENDER_REJECT_TAKEN;
		module.addCentralAsyncCommand(loadData, giftData);
		
	}
	
	
	public static void OnSendGiftGetRejectedOrderCallBack(int messageType, GiftPlayerData giftData, SendGiftNotifyModel model, ArrayList<PlayerItemModel> sendGiftItems) {
		SaveGiftNotifyTakenStageAsync saveData = new SaveGiftNotifyTakenStageAsync();
		saveData.messageType = messageType;
		saveData.model = model;
		saveData.giftData = giftData;
		saveData.orderID = model.getSendOrderID();
		saveData.playerIP = giftData.playerData.getLastloginIP();
		saveData.sendGiftItems = sendGiftItems;
		saveData.success = false;
		saveData.key = transformOrderIdToGuid(model.getSendOrderID());
		giftData.module.addAsyncCommand(saveData);
		
	}
	
	public static void OnSendGiftFinalTaken(GUID sessionID ,SendGiftRequest request, GameLobbyModule module){
		SendGiftResponse response = new SendGiftResponse();
		
		int messageType = MessageTypes.S_GIFT_FINAL_TAKEN_RESPONSE;
		
		if(module.isStopTransaction()){
			response.errorCode = ErrorCode.GAME_SERVER_WAIT_TO_CLOSE;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		if(request == null){
			//參數不正確
			response.errorCode = ErrorCode.INVALID_PARAM;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		if(request.orderID == 0L){
			//沒有訂單資料
			response.errorCode = ErrorCode.SEND_GIFT_ORDER_NULL;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}

		Player playerData =null;
		GUID playerID = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		if(playerID != null){
			playerData = module.getZone().getPlayer(playerID);
		}
		if(playerData == null){
			//是否有玩家資料
			response.errorCode = ErrorCode.NO_PLAYER_DATA;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		//確認會員限制
		int limitCode = GameLimitInfo.checkLimitByClassify(GameLimitInfo.TRANS_REV_GIFT, playerData.getVip(),playerData.getLevel(), playerData.isVerifiedMember(), playerData.isTrialAccount(), playerData.getUplineCode());
		if(limitCode != GameLimitInfo.TRUE){
			response.errorCode = GameLimitInfo.limitToErrorCode(limitCode);
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}	
		
		if(playerData.getLevel() < RECEIVE_GIFT_MIN_LEVEL){
			//玩家等級不足
			response.errorCode = ErrorCode.PLAYER_LEVEL_NOT_ENOUGH;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		
		boolean answer = request.answer; 
		//回覆是或否
		response.answer = answer;
		
		GiftPlayerData giftData = new GiftPlayerData();
		giftData.module = module;
		giftData.sessionID = sessionID;
		giftData.response = response;
		giftData.playerData = playerData;
		
		LoadSendGiftOrderDCLAsync loadData = new LoadSendGiftOrderDCLAsync();
		loadData.messageType = messageType;
		loadData.setQueueID(request.orderID.hashCode()); //分配道相同執行緒用
		loadData.orderID = request.orderID;
		loadData.playerID = playerID;
		loadData.nextStage = SendGiftStage.FINAL_TAKEN;
		module.addCentralAsyncCommand(loadData, giftData);
	}
	
	public static void OnSendGiftFinalTakenCallBack(int messageType, GiftPlayerData giftData, SendGiftNotifyModel model, ArrayList<PlayerItemModel> sendGiftItems) {
		SaveGiftNotifyTakenStageAsync saveData = new SaveGiftNotifyTakenStageAsync();
		saveData.messageType = messageType;
		saveData.model = model;
		saveData.giftData = giftData;
		saveData.orderID = model.getSendOrderID();
		saveData.playerIP = giftData.playerData.getLastloginIP();
		saveData.sendGiftItems = sendGiftItems;
		saveData.success = true;
		saveData.key = transformOrderIdToGuid(model.getSendOrderID());
		giftData.module.addAsyncCommand(saveData);
		
	}
	
	public static void OnSendGiftGetTimeoutOrder(GUID sessionID ,SendGiftRequest request, GameLobbyModule module){
		SendGiftResponse response = new SendGiftResponse();
		
		int messageType = MessageTypes.S_GIFT_GET_TIME_OUT_ORDER_RESPONSE;
		
		if(module.isStopTransaction()){
			response.errorCode = ErrorCode.GAME_SERVER_WAIT_TO_CLOSE;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		if(request == null){
			//參數不正確
			response.errorCode = ErrorCode.INVALID_PARAM;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
	
		if(request.orderID == 0L){
			//沒有訂單資料
			response.errorCode = ErrorCode.SEND_GIFT_ORDER_NULL;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		Player playerData =null;
		GUID playerID = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		if(playerID != null){
			playerData = module.getZone().getPlayer(playerID);
		}
		if(playerData == null){
			//是否有玩家資料
			response.errorCode = ErrorCode.NO_PLAYER_DATA;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		//確認會員限制
		int limitCode = GameLimitInfo.checkLimitByClassify(GameLimitInfo.TRANS_REV_GIFT, playerData.getVip(),playerData.getLevel(), playerData.isVerifiedMember(), playerData.isTrialAccount(), playerData.getUplineCode());
		if(limitCode != GameLimitInfo.TRUE){
			response.errorCode = GameLimitInfo.limitToErrorCode(limitCode);
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}	
		
		if(playerData.getLevel() < RECEIVE_GIFT_MIN_LEVEL){
			//玩家等級不足
			response.errorCode = ErrorCode.PLAYER_LEVEL_NOT_ENOUGH;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		boolean answer = request.answer; 
		//回覆是或否
		response.answer = answer;
		
		GiftPlayerData giftData = new GiftPlayerData();
		giftData.module = module;
		giftData.sessionID = sessionID;
		giftData.response = response;
		giftData.playerData = playerData;
		
		LoadSendGiftOrderDCLAsync loadData = new LoadSendGiftOrderDCLAsync();
		loadData.messageType = messageType;
		loadData.setQueueID(request.orderID.hashCode()); //分配道相同執行緒用
		loadData.orderID = request.orderID;
		loadData.playerID = playerID;
		loadData.nextStage = SendGiftStage.TIME_OUT_OREDER_TAKEN;
		module.addCentralAsyncCommand(loadData, giftData);
	}

	public static void OnSendGiftGetTimeoutOrderCallBack(int messageType, GiftPlayerData giftData, SendGiftNotifyModel model, 
			ArrayList<PlayerItemModel> sendGiftItems) {
		SaveGiftNotifyTakenStageAsync saveData = new SaveGiftNotifyTakenStageAsync();
		saveData.messageType = messageType;
		saveData.model = model;
		saveData.giftData = giftData;
		saveData.orderID = model.getSendOrderID();
		saveData.playerIP = giftData.playerData.getLastloginIP();
		saveData.sendGiftItems = sendGiftItems;
		saveData.success = false;
		saveData.key = transformOrderIdToGuid(model.getSendOrderID());
		giftData.module.addAsyncCommand(saveData);
	}
	
	public static void OnSendGiftGetGMReturnOrder(GUID sessionID ,SendGiftRequest request, GameLobbyModule module){
		SendGiftResponse response = new SendGiftResponse();
		
		int messageType = MessageTypes.S_GIFT_GET_GMTOOL_RETURN_ORDER_RESPONSE;
		
		if(module.isStopTransaction()){
			response.errorCode = ErrorCode.GAME_SERVER_WAIT_TO_CLOSE;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		if(request == null){
			//參數不正確
			response.errorCode = ErrorCode.INVALID_PARAM;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
	
		if(request.orderID == 0L){
			//沒有訂單資料
			response.errorCode = ErrorCode.SEND_GIFT_ORDER_NULL;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		Player playerData =null;
		GUID playerID = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		if(playerID != null){
			playerData = module.getZone().getPlayer(playerID);
		}
		if(playerData == null){
			//是否有玩家資料
			response.errorCode = ErrorCode.NO_PLAYER_DATA;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		//確認會員限制
		int limitCode = GameLimitInfo.checkLimitByClassify(GameLimitInfo.TRANS_REV_GIFT, playerData.getVip(),playerData.getLevel(), playerData.isVerifiedMember(), playerData.isTrialAccount(), playerData.getUplineCode());
		if(limitCode != GameLimitInfo.TRUE){
			response.errorCode = GameLimitInfo.limitToErrorCode(limitCode);
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}	
		
		if(playerData.getLevel() < RECEIVE_GIFT_MIN_LEVEL){
			//玩家等級不足
			response.errorCode = ErrorCode.PLAYER_LEVEL_NOT_ENOUGH;
			MessageAction.sendMessage(sessionID, messageType, response);
			return;
		}
		
		boolean answer = request.answer; 
		//回覆是或否
		response.answer = answer;
		
		GiftPlayerData giftData = new GiftPlayerData();
		giftData.module = module;
		giftData.sessionID = sessionID;
		giftData.response = response;
		giftData.playerData = playerData;
		
		LoadSendGiftOrderDCLAsync loadData = new LoadSendGiftOrderDCLAsync();
		loadData.messageType = messageType;
		loadData.setQueueID(request.orderID.hashCode()); //分配道相同執行緒用
		loadData.orderID = request.orderID;
		loadData.playerID = playerID;
		loadData.nextStage = SendGiftStage.GMTOOL_RETURN_ORDER_TAKEN;
		module.addCentralAsyncCommand(loadData, giftData);
	}

	public static void OnGetGMReturnOrderCallBack(int messageType, GiftPlayerData giftData, SendGiftNotifyModel model, 
			ArrayList<PlayerItemModel> sendGiftItems) {
		SaveGiftNotifyTakenStageAsync saveData = new SaveGiftNotifyTakenStageAsync();
		saveData.messageType = messageType;
		saveData.model = model;
		saveData.giftData = giftData;
		saveData.orderID = model.getSendOrderID();
		saveData.playerIP = giftData.playerData.getLastloginIP();
		saveData.sendGiftItems = sendGiftItems;
		saveData.success = false;
		saveData.key = transformOrderIdToGuid(model.getSendOrderID());
		giftData.module.addAsyncCommand(saveData);
	}
	/*** 以  *** 上 *** 虛 *** 寶 *** 交 *** 易 *** 過 **** 程 ***/
	
	/**
	 * @param sessionID
	 * @param request
	 * @param module
	 * 讀取所有通知列表
	 */
	public static void OnSendGiftGetAllNotify(GUID sessionID , GameLobbyModule module){
		SendGiftAllNotifyResponse response = new SendGiftAllNotifyResponse();
		
		GUID playerID = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		
		Player playerData = module.getZone().getPlayer(playerID);
		
		if(playerData == null){
			//是否有玩家資料
			response.errorCode = ErrorCode.NO_PLAYER_DATA;
			MessageAction.sendMessage(sessionID, MessageTypes.S_GIFT_GET_ALL_NOTIFY_RESPONSE, response);
			return;
		}
		
		LoadAllNotifyDataAsync loadData = new LoadAllNotifyDataAsync();
		loadData.playerID = playerID;
		loadData.sessionID = sessionID;
		loadData.response = response;
		loadData.key = playerID;
		module.addAsyncCommand(loadData);
	}

	/**
	 * @param sessionID
	 * @param request
	 * @param module
	 * 讀取交易記錄，只取完成紀錄
	 */
	public static void OnSendGiftGetRecord(GUID sessionID , SendGiftRequest request, GameLobbyModule module)
	{
		SendGiftAllNotifyResponse response = new SendGiftAllNotifyResponse();
		
		GUID playerID = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		if(playerID == null){
			//是否有玩家資料
			response.errorCode = ErrorCode.NO_PLAYER_DATA;
			MessageAction.sendMessage(sessionID, MessageTypes.S_GIFT_GET_RECORD_RESPONSE, response);
			return;
		}
		
		if(request == null){
			//參數不正確
			response.errorCode = ErrorCode.INVALID_PARAM;
			MessageAction.sendMessage(sessionID, MessageTypes.S_GIFT_GET_RECORD_RESPONSE, response);
			return;
		}
		
		if(request.start < 0 || request.length < 0){
			//參數不正確
			response.errorCode = ErrorCode.INVALID_PARAM;
			MessageAction.sendMessage(sessionID, MessageTypes.S_GIFT_GET_RECORD_RESPONSE, response);
			return;
		}
		
		LoadGiftRecordDataAsync loadData = new LoadGiftRecordDataAsync();
		loadData.playerID = playerID;
		loadData.sessionID = sessionID;
		loadData.response = response;
		loadData.start = request.start;
		loadData.length = request.length;
		loadData.key = playerID;
		module.addAsyncCommand(loadData);
		
	}
	
	/**
	 * @param sessionID
	 * @param request
	 * @param module
	 * 讀取交易記錄，只取完成紀錄
	 */
	public static void OnSendGiftGetRecordDetail(GUID sessionID , SendGiftRequest request, GameLobbyModule module)
	{
		SendGiftAllNotifyResponse response = new SendGiftAllNotifyResponse();
		
		GUID playerID = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		if(playerID == null){
			//是否有玩家資料
			response.errorCode = ErrorCode.NO_PLAYER_DATA;
			MessageAction.sendMessage(sessionID, MessageTypes.S_GIFT_GET_RECORD_DETAIL_RESPONSE, response);
			return;
		}
		
		if(request.orderID == 0L){
			//參數不正確
			response.errorCode = ErrorCode.SEND_GIFT_ORDER_NULL;
			MessageAction.sendMessage(sessionID, MessageTypes.S_GIFT_GET_RECORD_DETAIL_RESPONSE, response);
			return;
		}
		
		LoadRecordDetailDataAsync loadData = new LoadRecordDetailDataAsync();
		loadData.playerID = playerID;
		loadData.sessionID = sessionID;
		loadData.orderID = request.orderID;
		loadData.response = response;
		loadData.key = playerID;
		module.addAsyncCommand(loadData);
		
	}
	
	/**
	 * @param sessionID
	 * @param request
	 * @param module
	 * 更新列表和錢，逾時處理
	 */
	public static void OnUpdateMoneyNotify(GUID sessionID , GameLobbyModule module)
	{
		
		SendGiftResponse response = new SendGiftResponse();
		
		GUID playerID = PlayerCommonInfoManager.getInstance().getPlayerGuidBySession(sessionID);
		
		Player playerData = module.getZone().getPlayer(playerID);
		
		if(playerData == null){
			//是否有玩家資料
			response.errorCode = ErrorCode.NO_PLAYER_DATA;
			MessageAction.sendMessage(sessionID, MessageTypes.S_GIFT_CHECK_TIME_OUT_RESPONSE, response);
			return;
		}
		
		LoadAllNotifyDCLAsync loadData = new LoadAllNotifyDCLAsync();
		loadData.key = playerID;
		loadData.playerID = playerID;
		loadData.playerIP = PlayerCommonInfoManager.getInstance().getClientIpBySessionId(sessionID);
		loadData.sessionID = sessionID;
		module.addCentralAsyncCommand(loadData, module, playerData, response);
		
	}
	
	/**
	 * 讀取所有通知列表,先判斷是否有過時的資料,有的話處理
	 * @see LoadAllNotifyDCLAsync#callBackExecute(Object...)
	 * @see GameLobbyModule#sendGiftTimeOutCallBack(BaseDataInfo, Object...)
	 */
	public static void OnUpdateMoneyCallBack(GUID sessionID, GUID playerID, Player playerData, String playerIP,
			GameLobbyModule module, SendGiftResponse response,
			ArrayList<PlayerItemModel> timeOutGiftItems)	{
		//如果沒有自己的過時資料 就結束
		
			//如果沒有sessionID 就是被GmTool強制讀取所有通知列表
			if(sessionID == null)
				return;
			response.nowGoldCoin = "-1";
			response.errorCode = ErrorCode.SUCCESS;
			MessageAction.sendMessage(sessionID, MessageTypes.S_GIFT_CHECK_TIME_OUT_RESPONSE, response);
			return;
	}

//	/**
//	 * 網頁虛寶交易 取得交易明細 
//	 * @param playerId 腳色ID 
//	 * @param pageNum 要的頁數
//	 * @return
//	 */
//	public static List<Object> WebTransactionGetRecordByPage(GUID playerId , int pageNum){
//		LinkedList<Object> result = new LinkedList<Object>();
//		// 計算頁數、取資料的起始位置
//		if (pageNum < 1) {
//			pageNum = 1;
//		}
//
//		int maxPerPage = WEB_TRANSACTION_RECORD_MAX_PRE_PAGE;
//		int beginPos = (pageNum - 1) * maxPerPage;
//		
//		long dataCount = SendGiftRecordDAO.getTotalRecordCountByGUID(playerId);
//			
//		Long MaxPage = (long) GameUtility.calculatePageCount((int)dataCount, maxPerPage);
//		result.add(MaxPage.intValue());
//		
//		//如果pageNum > 
//		if(beginPos >= MaxPage * WEB_TRANSACTION_RECORD_MAX_PRE_PAGE){
//			beginPos = (MaxPage.intValue()-1) * WEB_TRANSACTION_RECORD_MAX_PRE_PAGE;
//		}
//
//		
//		List records = SendGiftRecordDAO.getNotifyDatasByPage(playerId, beginPos, maxPerPage);
//		 
//		ArrayList<NotifyData> notifyDatas = new ArrayList<NotifyData>();
//		Iterator it = records.iterator();
//		while (it.hasNext()) {
//			Map map = (Map) it.next();
//			String stageListStr = (String) map.get("stageList");
//			SendGiftRecordLog model = (SendGiftRecordLog) map.get("SendGiftRecordLog");
//			ArrayList<PlayerItemModel> sendGiftItems = ItemDAO.loadSendGiftItems(model.getOrderID());
//			NotifyData data = new NotifyData(model.getPlayerGUID().toString(), model, stageListStr, sendGiftItems);
//			notifyDatas.add(data);
//		}
//
//		result.addFirst(notifyDatas);
//		
//		return result;
//	}
	
	public static void main(String[] args) {
		System.setProperty("log4j.configurationFile", "./config/log4j2.xml");
		InitData.initAll();
		GUIDFactory.setWorldId(1);
		GUIDFactory.setProcessId(1);
		
//		System.out.println(transformOrderIdToGuid(18173073567121683l).toString());
		
		
		
//		Session session = HibernateLogManager.getSession();
//				
//		SQLQuery SqlQuery = session.createSQLQuery("select * from ("
//				+ "select  s.sendOrderID 'ID' ,GROUP_CONCAT(s.stage)  as 'lists' from "
//				+ "(select r.* from send_gift_record r order by r.sendOrderID desc ,r.stage desc) s   "
//				+ "group by s.sendOrderID order by s.stage desc ) d "
//				+ "where (d.lists != '3,2,1')  and  (d.lists != '1,1')  and  (d.lists != '2,1') and (d.lists != '5,2,1') and (d.lists != '4,1') "
//				+ "and (d.lists != '5,1')");
//		SqlQuery.setResultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP);
//		SqlQuery.addScalar("lists", StandardBasicTypes.STRING);
//		SqlQuery.addScalar("ID", StandardBasicTypes.LONG);
//		List modelss = SqlQuery.list();
//		HibernateLogManager.endSession();
//		
//
//		Iterator it = modelss.iterator();
//		Session session2 = HibernateLogManager.txBegin();
//		while (it.hasNext()) {
//			Map map = (Map)it.next();
//			String stageListStr = (String) map.get("lists");
//			long id = (Long)map.get("ID");
//			
//
//			Query query = session2.createQuery("delete from SendGiftRecordLog where sendOrderID = :ID and taken = false and stage = :STAGE");
//			query.setParameter("ID", id);
//			
//			if(stageListStr.equals("5,4,1")){
//				query.setParameter("STAGE", 4);
//			}
//			
//			if(stageListStr.equals("4,1,1")){
//				query.setParameter("STAGE", 4);
//			}
//			
//			if(stageListStr.equals("4,4,1")){
//				query.setParameter("STAGE", 4);
//			}
//			
//			if(stageListStr.equals("2,2,1")){
//				query.setParameter("STAGE", 2);
//				
//			}
//			
//			if (stageListStr.equals("2,2,2,1")) {
//				query.setParameter("STAGE", 2);
//			}
//			
//			if(stageListStr.equals("1,1,1")){
//				query.setParameter("STAGE", 1);
//			}
//			
//			if(stageListStr.equals("1")){
//				continue;
//			}
//			
//			query.executeUpdate();
//			session2.flush();
//		}
//		HibernateLogManager.txCommitFailRollbackClearSession();
//
//
//		session = HibernateLogManager.getSession();
//		Query query = session.createQuery("select s From SendGiftRecordLog s where s.taken = true order by stage desc");
//		ArrayList<SendGiftRecordLog> models = (ArrayList<SendGiftRecordLog>) query.list();
//		HibernateLogManager.endSession();
//		
//		session = HibernateLogManager.getSession();
//		Transaction tx = session.beginTransaction();
//		tx.begin();
//		SendGiftRecordLog notTakenModel = new SendGiftRecordLog();
//		for (SendGiftRecordLog model : models) {
//		
//			int stage = model.getStage();
//			
//			if(stage == 5 && model.isTaken()){
//				//原本GMTool 單筆退回
//				model.setStage(SendGiftStage.GMTOOL_RETURN_ORDER_TAKEN);
//				model.setOrderFinishTime(model.getCompleteTime());
//				model.setSendbackTime(model.getCompleteTime());
//				model.setFinalTakenTime(model.getCompleteTime());
//				model.setOutTakenTime(model.getOutTakenTime());
//				model.setCompleteTime(null);
//				session.saveOrUpdate(model);
//				session.flush();
//				
//				SendGiftRecordLog to = translate(model);
//				to.setStage(SendGiftStage.FORCE_SEND_GIFT_RETURN_BY_GMTOOL);
//				to.setAnswerTime(model.getAnswerTime());
//				to.setCompleteTime(model.getCompleteTime());
//				
//				session.save(to);
//			}
//			
//			else if(stage == 4 && model.isTaken()){
//				//原本被GMtool禁止交易退回
//				
//				model.setStage(SendGiftStage.GMTOOL_RETURN_ORDER_TAKEN);
//				model.setOrderFinishTime(model.getCompleteTime());
//				model.setSendbackTime(model.getCompleteTime());
//				model.setFinalTakenTime(model.getCompleteTime());
//				model.setOutTakenTime(model.getOutTakenTime());
//				model.setCompleteTime(null);
//				session.saveOrUpdate(model);
//				session.flush();
//				
//				SendGiftRecordLog to = translate(model);
//				to.setStage(SendGiftStage.DISABLE_SEND_BY_GMTOOL);
//				to.setAnswerTime(model.getAnswerTime());
//				to.setCompleteTime(model.getCompleteTime());
//				
//				session.save(to);
//			}
//			
//			else if(stage == 3){
//				//原本完成
//				model.setStage(SendGiftStage.FINAL_TAKEN);
//				model.setOrderFinishTime(model.getCompleteTime());
//				model.setFinalTakenTime(model.getCompleteTime());
//				model.setSuccess(true);
//				session.saveOrUpdate(model);
//				session.flush();
//				
//				SendGiftRecordLog to = translate(model);
//				to.setStage(SendGiftStage.FINIAL_SEND);
//				to.setAnswerTime(model.getAnswerTime());
//				to.setCompleteTime(model.getCompleteTime());
//				to.setSuccess(true);
//				session.save(to);
//			}
//			
//			else if(stage == 2 && model.getOutTakenTime() != null){
//				//在第二步過期
//				model.setStage(SendGiftStage.TIME_OUT_OREDER_TAKEN);
//				model.setOrderFinishTime(model.getCompleteTime());
//				model.setSendbackTime(model.getCompleteTime());
//				model.setFinalTakenTime(model.getCompleteTime());
//				model.setOutTakenTime(model.getOutTakenTime());
//				model.setCompleteTime(null);
//				session.saveOrUpdate(model);
//				session.flush();
//				
//				SendGiftRecordLog to = translate(model);
//				to.setStage(SendGiftStage.TIME_OUT_ORDER_RETURN);
//				to.setAnswerTime(model.getAnswerTime());
//				session.save(to);
//			}
//			
//			else if(stage == 2){
//				//原本對方拒絕
//				model.setStage(SendGiftStage.SENDER_REJECT_TAKEN);
//				model.setFinalTakenTime(model.getCompleteTime());
//				model.setOrderFinishTime(model.getCompleteTime());
//				model.setCompleteTime(null);
//				session.saveOrUpdate(model);
//				session.flush();
//				
//				SendGiftRecordLog to = translate(model);
//				to.setStage(SendGiftStage.SECOND_REJECT);
//				to.setAnswerTime(model.getAnswerTime());
//				session.save(to);
//			}
//			
//			else if(stage == 1 && model.getOutTakenTime() != null){
//				//在第一步過期
//				model.setStage(SendGiftStage.TIME_OUT_OREDER_TAKEN);
//				model.setOrderFinishTime(model.getCompleteTime());
//				model.setSendbackTime(model.getCompleteTime());
//				model.setFinalTakenTime(model.getCompleteTime());
//				model.setOutTakenTime(model.getOutTakenTime());
//				model.setCompleteTime(null);
//				session.saveOrUpdate(model);
//				session.flush();
//				
//				SendGiftRecordLog to = translate(model);
//				to.setStage(SendGiftStage.TIME_OUT_ORDER_RETURN);
//				to.setAnswerTime(model.getAnswerTime());
//				session.save(to);
//				
//			}
//			
//			else if(stage == 1 && model.isTaken()) {
//				//原本的自己取消 
//				model.setStage(SendGiftStage.FIRST_CANCEL);
//				model.setFinalTakenTime(model.getCompleteTime());
//				model.setOrderFinishTime(model.getCompleteTime());
//				model.setCompleteTime(null);
//				session.saveOrUpdate(model);
//				session.flush();
//				
//				SendGiftRecordLog to = translate(model);
//				to.setStage(SendGiftStage.FIRST_CANCEL);
//				to.setAnswerTime(model.getAnswerTime());
//				session.save(to);
//			}
//		}
//		try{
//			tx.commit();
//		}catch(Exception e){
//			System.out.println(e.getStackTrace());
//			tx.rollback();
//		}
//
//		HibernateLogManager.endSession();
	}
	
	private static SendGiftRecordLog translate(SendGiftRecordLog from){
		SendGiftRecordLog to = new SendGiftRecordLog();
		to.setPlayerGUID(from.getPlayerGUID());
		to.setPlayerName(from.getPlayerName());
		to.setPlayerIP(null);
		to.setTargetGUID(from.getTargetGUID());
		to.setTargetName(from.getTargetName());
		to.setTargetIP(null);
		to.setCreateTime(from.getCreateTime());
		to.setGameTime(from.getGameTime());
		to.setEventTime(from.getEventTime());
		to.setEventDate(from.getEventDate());
		to.setGoldCoin(from.getGoldCoin());
		to.setItems(from.getItems());
		to.setOrderID(from.getOrderID());
		to.setSendOrderID(from.getSendOrderID());
		to.setOrderNumber(from.getOrderNumber());
		to.setServiceCharge(from.getServiceCharge());
		to.setOverTime(from.getOverTime());
		to.setOrderFinishTime(from.getOrderFinishTime());
		to.setSendbackTime(from.getSendbackTime());
		to.setFinish(from.isFinish());
		to.setTaken(false);
		return to;
	}


	
	/**
	 * 將 sendOrderId 轉成 GUID
	 * @param orderId
	 * @return
	 */
	private static GUID transformOrderIdToGuid(Long orderId){
		ByteBuffer buffer = ByteBuffer.allocate(Long.SIZE / Byte.SIZE);
		buffer.putLong(orderId);
		byte[] array = buffer.array();
		
		byte[] parseArray = new byte[3];
		
		parseArray = Arrays.copyOfRange(array,0,4);
		int firstId = ByteBuffer.wrap(parseArray).getInt();
		
		parseArray = Arrays.copyOfRange(array,2,6);
		int secId = ByteBuffer.wrap(parseArray).getInt();
		
		parseArray = Arrays.copyOfRange(array,4,8);
		int lastId =  ByteBuffer.wrap(parseArray).getInt();
		
		GUID orderGUID = new GUID(firstId, secId, lastId);
		
		return orderGUID;
		
	}
}
